/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.almeros.ohos.multitouch.example.slice;

import com.almeros.ohos.multitouch.example.ResourceTable;
import com.almeros.ohos.multitouch.library.MoveGestureDetector;
import com.almeros.ohos.multitouch.library.RotateGestureDetector;
import com.almeros.ohos.multitouch.library.ScaleGestureDetector;
import com.almeros.ohos.multitouch.library.ShoveGestureDetector;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentTreeObserver;
import ohos.agp.components.Image;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.Matrix;
import ohos.global.resource.RawFileEntry;
import ohos.global.resource.ResourceManager;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.multimodalinput.event.TouchEvent;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;

/**
 * MainAbility
 *
 * @author ljx
 * @since 2021-05-08
 */
public class MainAbilitySlice extends AbilitySlice implements Component.TouchEventListener {

    private Image image;
    private Matrix mMatrix = new Matrix();
    private float mScaleFactor = 1f;
    private float mRotationDegrees = 0f;
    private float mFocusX = 0f;
    private float mFocusY = 0f;
    private float mAlpha = 1;
    private float mImageHeight, mImageWidth;
    private float curX;
    private float curY;

    private RotateGestureDetector mRotateDetector;
    private ScaleGestureDetector mScaleDetector;
    private MoveGestureDetector mMoveDetector;
    private ShoveGestureDetector mShoveDetector;
    //添加一个全局变量PixelMapHolder用于传递图片，解决鸿蒙操作canvas时图像不变换的问题
    private PixelMapHolder mBitmapHolder;
    private PixelMap pixelMap;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        image = (Image) findComponentById(ResourceTable.Id_image);
        image.setTouchEventListener(this);

        ImageSource imageSource;
        ResourceManager resManager = getResourceManager();
        RawFileEntry rawFileEntry = resManager.getRawFileEntry("resources/rawfile/earth.png");
        try {
            InputStream resource = rawFileEntry.openRawFile();
            imageSource = ImageSource.create(resource, null);
            pixelMap = imageSource.createPixelmap(null);
        } catch (IOException e) {
            System.out.println(e);
        }
        if (pixelMap != null) {
            // 全局变量 PixelMapHolder
            mBitmapHolder = new PixelMapHolder(pixelMap);
        }
        image.getComponentTreeObserver().addWindowBoundListener(new ComponentTreeObserver.WindowBoundListener() {

            @Override
            public void onWindowBound() {
                mFocusX = image.getWidth() / 2f;
                mFocusY = image.getHeight() / 2f;
                mImageWidth = pixelMap.getImageInfo().size.width;
                mImageHeight = pixelMap.getImageInfo().size.height;
                float scaledImageCenterX = (mImageWidth * mScaleFactor) / 2F;
                float scaledImageCenterY = (mImageHeight * mScaleFactor) / 2F;
                mMatrix.postScale(mScaleFactor, mScaleFactor);
                BigDecimal bignum1 = new BigDecimal(mFocusX);
                BigDecimal bignum2 = new BigDecimal(scaledImageCenterX);
                BigDecimal bignum3 = new BigDecimal(mFocusY);
                BigDecimal bignum4 = new BigDecimal(scaledImageCenterY);
                mMatrix.postTranslate(bignum1.subtract(bignum2).floatValue(), bignum3.subtract(bignum4).floatValue());
                image.addDrawTask(new Component.DrawTask() {

                    @Override
                    public void onDraw(Component component, Canvas canvas) {
                        canvas.save();
                        canvas.setMatrix(mMatrix);
                        canvas.drawPixelMapHolder(mBitmapHolder, 0, 0, new Paint());
                        canvas.restore();
                    }
                });
            }

            @Override
            public void onWindowUnbound() {

            }
        });

        mScaleDetector = new ScaleGestureDetector(new ScaleListener());
        mRotateDetector = new RotateGestureDetector(new RotateListener());
        mMoveDetector = new MoveGestureDetector(new MoveListener());
        mShoveDetector = new ShoveGestureDetector(new ShoveListener());
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        mScaleDetector.onTouchEvent(event);
        mRotateDetector.onTouchEvent(event);
        mMoveDetector.onTouchEvent(event);
        mShoveDetector.onTouchEvent(event);

        float scaledImageCenterX = (mImageWidth * mScaleFactor) / 2F;
        float scaledImageCenterY = (mImageHeight * mScaleFactor) / 2F;
        mMatrix.reset();
        mMatrix.postScale(mScaleFactor, mScaleFactor);
        mMatrix.postRotate(mRotationDegrees, scaledImageCenterX, scaledImageCenterY);

        BigDecimal bignum1 = new BigDecimal(mFocusX);
        BigDecimal bignum2 = new BigDecimal(scaledImageCenterX);
        BigDecimal bignum3 = new BigDecimal(curX);
        BigDecimal bignum4 = new BigDecimal(mFocusY);
        BigDecimal bignum5 = new BigDecimal(scaledImageCenterY);
        BigDecimal bignum6 = new BigDecimal(curY);
        mMatrix.postTranslate(bignum1.subtract(bignum2).add(bignum3).floatValue(), bignum4.subtract(bignum5).add(bignum6).floatValue());
        image.addDrawTask(new Component.DrawTask() {

            @Override
            public void onDraw(Component component, Canvas canvas) {
                canvas.save();
                canvas.setMatrix(mMatrix);
                canvas.drawPixelMapHolder(mBitmapHolder, 0, 0, new Paint());
                canvas.restore();
            }
        });
        image.setAlpha(mAlpha);
        return true;
    }

    private class RotateListener extends RotateGestureDetector.SimpleOnRotationGestureListener {

        @Override
        public boolean onRotation(RotateGestureDetector rotationDetector) {
            mRotationDegrees = rotationDetector.getAngle();
            return false;
        }
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

        @Override
        public boolean onScale(ScaleGestureDetector scaleDetector) {
            mScaleFactor = scaleDetector.getScale();
            return false;
        }
    }

    private class MoveListener extends MoveGestureDetector.SimpleOnScaleGestureListener {

        @Override
        public boolean onMove(MoveGestureDetector detector) {
            curX = detector.getX();
            curY = detector.getY();
            return false;
        }
    }

    private class ShoveListener extends ShoveGestureDetector.SimpleOnShoveGestureListener {

        @Override
        public boolean onShove(ShoveGestureDetector detector) {
            mAlpha =  detector.getShovePixelsDelta();
            if (mAlpha > 1){
                mAlpha = 1;
            }
            if (mAlpha < 0){
                mAlpha = 0;
            }
            return false;
        }
    }
}